#  This is part of Scopia Visual Framework
#
#  wxWidgets openGL adaptor classes and functions
#
#  Copyright (C) 2008  Scopia Visual Interfaces Systems 
#                      http://www.scopia.es
#
#  author: Alejandro Conty
#  contributors:
#
#  This program is free software: you can redistribute it and/or modify
#  it under the terms of the GNU General Public License as published by
#  the Free Software Foundation, either version 3 of the License, or
#  (at your option) any later version.
#
#  This program is distributed in the hope that it will be useful,
#  but WITHOUT ANY WARRANTY; without even the implied warranty of
#  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#  GNU General Public License for more details.
#
#  You should have received a copy of the GNU General Public License
#  along with this program.  If not, see <http://www.gnu.org/licenses/>.

import wx
from wx.glcanvas import *
from scopiavf.adaptors import *
import os,sys
import sys
from OpenGL.GL import glViewport

#oldexitfunc = None
#if hasattr(sys, 'exitfunc'):
#oldexitfunc = sys.exitfunc
#def cleanup():
#if oldexitfunc: oldexitfunc()
#sys.exitfunc = cleanup

class wxAdaptor_t(GLCanvas, adaptor_t):
    "OpenGL adaptor for wxWidgets, can be placed as a normal widget everywhere"

    def __init__(self, parent, appfunc, *args,**kw):
        """Init function

                parent      Is the parent widget of this one
                appfunc     Is a function which is able to create an instance of an
                            opengl app (glContext_t derivate) whose creation is delayed
                            cause it needs a valid opengl context. Its arguments must be
                            width and height"""
        self.appfunc = appfunc
        self.GL_uninitialised = 1
        kw['attribList'] = [ WX_GL_RGBA, WX_GL_DOUBLEBUFFER ]
        GLCanvas.__init__(self, parent, *args,**kw)
        adaptor_t.__init__(self)
        wx.EVT_SIZE(self, self.wxSize)
        wx.EVT_PAINT(self, self.wxPaint)
        wx.EVT_ERASE_BACKGROUND(self, self.wxEraseBackground)
        self.w, self.h = self.GetClientSizeTuple()
        wx.EVT_CHAR(self,self.OnChar)
        wx.EVT_LEFT_DOWN(self,self.OnLeftDown)
        wx.EVT_LEFT_UP(self,self.OnLeftUp)
        wx.EVT_MIDDLE_DOWN(self,self.OnMiddleDown)
        wx.EVT_MIDDLE_UP(self,self.OnMiddleUp)
        wx.EVT_RIGHT_DOWN(self,self.OnRightDown)
        wx.EVT_RIGHT_UP(self,self.OnRightUp)
        wx.EVT_MOTION(self,self.wxMouseMotion)
        wx.EVT_MOUSEWHEEL(self, self.wxWheel)
        timerid = wx.NewId()
        self.timer = wx.Timer(self, timerid)
        wx.EVT_TIMER(self, timerid, self.wxTimer)
        self.app = None
        self.doresize = False

    def wxTimer(self, evt):
        self.app.timer()

    def wxSize(self, event = None):
      self.w, self.h = self.GetClientSizeTuple()
      if self.GetContext():
        self.SetCurrent()
        if self.app:
            self.app.width, self.app.height = self.w, self.h
        self.doresize = True
        if self.app: self.app.forceDisplay()

    def wxEraseBackground(self, event): pass

    def wxPaint(self, event=None):
        dc = wx.PaintDC(self)
        self.SetCurrent()

        if self.GL_uninitialised:
            glViewport(0, 0, self.w, self.h)
            self.app = self.appfunc(self.w, self.h)
            del self.appfunc
            def redisplay(w):
                self.Refresh()
            self.app.forceDisplay = lambda : redisplay(self)
            self.timer.Start(10)
            self.GL_uninitialised=0
        
        #self.countFrames()
        if self.doresize:
            glViewport(0, 0, self.w, self.h)
            self.doresize = False
        self.app._display()
        self.SwapBuffers()
        if event: event.Skip() 
  
    def OnLeftDown(self,event):
        x, y = event.GetX(),event.GetY()
        b = (True,  False, False, False, False)
        self.app.mouse( b, True, x, y)

    def OnLeftUp(self,event):
        x, y = event.GetX(),event.GetY()
        b = (True,  False, False, False, False)
        self.app.mouse( b, False, x, y)
  
    def OnMiddleDown(self,event):
        x, y = event.GetX(),event.GetY()
        b = (False, True, False, False, False)
        self.app.mouse( b, True, x, y)

    def OnMiddleUp(self,event):
        x, y = event.GetX(),event.GetY()
        b = (False, True, False, False, False)
        self.app.mouse( b, False, x, y)

    def OnRightDown(self,event):
        x, y = event.GetX(),event.GetY()
        b = (False,  False, True, False, False)
        self.app.mouse( b, True, x, y)

    def OnRightUp(self,event):
        x, y = event.GetX(),event.GetY()
        b = (False,  False, True, False, False)
        self.app.mouse( b, False, x, y)
  
    def wxMouseMotion(self,event):
        if not event.Dragging():
            return
        x, y = event.GetX(),event.GetY()
        self.app.motion(x, y)
    
    def wxWheel(self, event):
        x, y = event.GetX(),event.GetY()
        clicks = event.GetWheelRotation() / event.GetWheelDelta()
        if clicks < 0:
            clicks = - clicks
            for i in xrange(clicks):
		        self.app.mouse( (False, False,  False, False, True), True, x, y)
        elif clicks > 0:
            for i in xrange(clicks):
		        self.app.mouse( (False, False,  False, True, False), True, x, y)
  
    def OnChar(self,event):
        key = event.GetKeyCode()
        self.app.keyboard( chr(key), 0, 0 )


